#include "blockqueue.hpp"
#include "task.hpp"
#include "SaveTask.hpp"
#include <pthread.h>
#include <unistd.h>
#include <string.h>
#include <ctime>


void *Consumer(void *args)
{
    BlockQueues<Task,SaveTask>* bq = static_cast<BlockQueues<Task,SaveTask> *>(args);
    while (true)
    {

        Task t;
        // 1. 将数据从blockqueue中获取 -- 获取到了数据
        bq->c_bq->pop(&t);
        t();
        std::string str1= t.formatArg();
        std::string result=str1.append(t.formatRes());
        // 2. 结合某种业务逻辑，处理数据！ -- TODO
        std::cout << pthread_self() << " | 消费任务之后的数据结果: " 
        << t.formatArg() << t.formatRes() << std::endl;
        //保存日志到磁盘
        SaveTask save(result,Save);
        bq->s_bq->push(save);
        std::cout<<"consumer thread,推送任务完成..."<<std::endl;
    }
    return nullptr;
}

void *Productor(void *args)
{
    BlockQueue<Task> *bq = (static_cast<BlockQueues<Task,SaveTask> *>(args))->c_bq;
    std::string opers="+-*/%";
    while (true)
    {
        
        sleep(1);
        // 1. 先通过某种渠道获取数据
        int x = rand() % 20 + 1;
        int y = rand() % 10 + 1;
        char op = opers[rand() % opers.size()];
        // 2. 将数据推送到blockqueue -- 完成生产过程
        Task t(x, y, op);
        bq->push(t);
        std::cout << pthread_self() << " | 生产者的任务: " 
        <<  t.formatArg() << "?" << std::endl;
    }
    return nullptr;
}

void* Saver(void* args){
    //只要保存日志任务的阻塞队列
    BlockQueue<SaveTask>* sav_bq=(static_cast<BlockQueues<Task,SaveTask>*>(args))->s_bq;
    while(true){
        sleep(1);
        SaveTask t;
        sav_bq->pop(&t);
        t();
        std::cout<<"saver thread,保存任务完成..."<<std::endl;
    }
    return nullptr;
}

int main(){
    //生产随机数种子
    srand((uint64_t)time(nullptr)^getpid());
    //创建阻塞队列
    BlockQueues<Task,SaveTask> bqs;
    bqs.c_bq=new BlockQueue<Task>();
    bqs.s_bq=new BlockQueue<SaveTask>();
    //创建消费者和生产者线程
     pthread_t c[2], p[3],s;
    pthread_create(&p[0], nullptr, Productor, &bqs);
    pthread_create(&p[1], nullptr, Productor, &bqs);
    pthread_create(&p[2], nullptr, Productor, &bqs);
    pthread_create(&c[0], nullptr, Consumer, &bqs);
    pthread_create(&c[1], nullptr, Consumer, &bqs);
    //保存线程
    pthread_create(&s,nullptr,Saver,&bqs);

    pthread_join(c[0], nullptr);
    pthread_join(c[1], nullptr);
    pthread_join(p[0], nullptr);
    pthread_join(p[1], nullptr);
    pthread_join(p[2], nullptr);

    delete bqs.c_bq;
    delete bqs.s_bq;
    return 0;
}
